/**
 * @file app.c
 * @author zhaitao (zhaitao.as@outlook.com)
 * @brief
 * @version 0.1
 * @date 2024-04-01
 *
 * @copyright zhaitao.as@outlook.com (c) 2024
 *
 */

#include "app.h"
#include "usbd_customhid.h" //包括发送函数头文件

#define BUFF_SIZE_USB 64
#define BUFF_SIZE_UART 512

#define EVENT_SYS 0
#define EVENT_AT 1
#define EVENT_CHN 2
#define EVENT_RST 3
#define EVENT_PWR 4

#define NODE_SIZE 256
#define NODE_CNT 40
struct Node {
	uint16_t size;
	uint8_t data[NODE_SIZE];
};

struct Node nodes[NODE_CNT];
int node_wr = 0;
int node_rd = 0;

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern USBD_HandleTypeDef hUsbDeviceFS; // 外部声明USB的句柄
extern DMA_HandleTypeDef hdma_usart2_rx;

uint8_t buff_usbtx[BUFF_SIZE_USB] = {0x55};
uint8_t buff_usbrx[BUFF_SIZE_USB]; // USB接收缓存
uint8_t cnt_usbrx = 0;		   // USB接收数据计数

uint8_t buff_u1rx[BUFF_SIZE_UART] = {0};
uint8_t buff_u1tx[BUFF_SIZE_UART] = {0};
uint8_t buff_u2rx[BUFF_SIZE_UART] = {0};
uint8_t buff_u2tx[BUFF_SIZE_UART] = {0};

uint32_t cnt_u1rx = 0;
uint32_t cnt_u2rx = 0;

uint8_t usb_state;
uint32_t usb_msg_delay = 150;

void app_start(void);
void app_out_event_cb(uint8_t event_idx, uint8_t state);
void app_sel_chn(uint16_t chn);
void app_ec800_reset(uint8_t state);
void app_pwr_4v0(uint8_t state);
void print_hex(uint8_t *buff, uint32_t size);

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart == &huart1) {
		cnt_u1rx = Size;
		HAL_UARTEx_ReceiveToIdle_IT(&huart1, buff_u1rx, BUFF_SIZE_UART);
	}

	if (huart == &huart2) {
		nodes[node_wr].size = Size;
		if ((node_wr + 1) >= NODE_CNT) {
			node_wr = 0;
		} else {
			node_wr++;
		}
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2, nodes[node_wr].data, BUFF_SIZE_UART);
	}
}

void app_start(void)
{
	HAL_UARTEx_ReceiveToIdle_IT(&huart1, buff_u1rx, BUFF_SIZE_UART);
	HAL_UARTEx_ReceiveToIdle_DMA(&huart2, nodes[node_wr].data, BUFF_SIZE_UART);
	__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

	app_pwr_4v0(0);
	HAL_Delay(300);
	app_sel_chn(1);
	HAL_Delay(30);
	app_pwr_4v0(1);
	HAL_Delay(300);
	app_ec800_reset(0);
	HAL_Delay(300);
	app_ec800_reset(1);
	HAL_Delay(300);

	for (;;) {
		HAL_Delay(5);

		if (cnt_u1rx) {
			HAL_UART_Transmit(&huart1, buff_u1rx, cnt_u1rx, 0xFFF);
			HAL_UART_Transmit(&huart2, buff_u1rx, cnt_u1rx, 0xFFF);

			cnt_u1rx = 0;
			memset(buff_u1rx, 0x00, BUFF_SIZE_UART);
		}

		if (node_rd != node_wr) {
			printf("======\r\n");
			HAL_UART_Transmit(&huart1, nodes[node_rd].data, nodes[node_rd].size, 0xFFF);
			printf("======\r\n");
			int16_t pack_cnt = nodes[node_rd].size / 62;
			uint16_t last_pack_size = nodes[node_rd].size % 62;
			int16_t pack_idx = pack_cnt;
			memset(buff_usbtx, 0x00, 64);
			buff_usbtx[0] = EVENT_AT;
			uint8_t *data_addr = nodes[node_rd].data;
			// printf("\r\nSize=%d CNT=%d\r\n", nodes[node_rd].size, pack_cnt);
			for (; pack_idx >= 0; pack_idx--) {
				buff_usbtx[1] = pack_idx;
				memset(&(buff_usbtx[2]), 0x00, 62);
				if (pack_idx == 0) {
					memcpy(&(buff_usbtx[2]), data_addr, last_pack_size);
				} else {
					memcpy(&(buff_usbtx[2]), data_addr, 62);
				}
				printf("@@@\r\n");
				HAL_UART_Transmit(&huart1, buff_usbtx, 64, 0xFFF);
				data_addr += 62;
				
				do {
					usb_state = USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, buff_usbtx, 64);
				} while (usb_state != USBD_OK);
				HAL_Delay(usb_msg_delay);
			}

			if ((node_rd + 1) >= NODE_CNT) {
				node_rd = 0;
			} else {
				node_rd++;
			}
		}
	}
}

void app_out_event_cb(uint8_t event_idx, uint8_t state)
{
	printf("out event id: %02x, state: %02x\r\n", event_idx, state);

	/*查看接收数据长度*/
	// 第一参数是USB句柄，第二个参数的是接收的末端地�?；要获取发�?�的数据长度的话就把第二个参数改为发送末端地�?即可
	cnt_usbrx = USBD_GetRxCount(&hUsbDeviceFS, CUSTOM_HID_EPOUT_ADDR);
	// printf("cnt_usbrx = %d \r\n",cnt_usbrx);

	// 定义1个指向USBD_CUSTOM_HID_HandleTypeDef结构体的指针
	USBD_CUSTOM_HID_HandleTypeDef *hhid;
	// 得到USB接收数据的储存地址
	hhid = (USBD_CUSTOM_HID_HandleTypeDef *)hUsbDeviceFS.pClassData;

	memcpy(buff_usbrx, hhid->Report_buf, cnt_usbrx);

	HAL_UART_Transmit(&huart1, buff_usbrx, cnt_usbrx, 0xfff);

	switch (event_idx) {
	case EVENT_SYS:
		/* 系统复位 */
		HAL_NVIC_SystemReset();
		break;
	case EVENT_AT:
		/* AT 命令转发 state是从AT开始的命令长度, 须以回车换行(0D, 0A)结尾*/
		HAL_UART_Transmit(&huart2, &(buff_usbrx[2]), state, 0xfff);
		break;
	case EVENT_CHN:
		/* 切换通道, */
		app_sel_chn(state);
		printf("chn = %d\r\n", state);
		break;
	case EVENT_RST:
		app_ec800_reset(state);
		break;
	case EVENT_PWR:
		app_pwr_4v0(state);
		break;
	default:
		break;
	}
}

void app_sel_chn(uint16_t chn)
{
	if ((chn < 1) || (chn > 32)) {
		buff_usbtx[0] = 2;
		buff_usbtx[1] = 1;
		USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, buff_usbtx, sizeof(buff_usbtx));
		return;
	}

	/* 1~32 -> 0~31(0~F, 0x10~0x1F)*/
	chn = chn - 1;
	uint8_t chip = chn / 16;
	chn = chn % 15;

	HAL_GPIO_WritePin(ASW_EN1_GPIO_Port, ASW_EN1_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(ASW_EN2_GPIO_Port, ASW_EN2_Pin, GPIO_PIN_SET);

	if (chn & 0x1) {
		HAL_GPIO_WritePin(ASW_S0_GPIO_Port, ASW_S0_Pin, GPIO_PIN_SET);
	} else {
		HAL_GPIO_WritePin(ASW_S0_GPIO_Port, ASW_S0_Pin, GPIO_PIN_RESET);
	}

	if (chn & 0x2) {
		HAL_GPIO_WritePin(ASW_S1_GPIO_Port, ASW_S1_Pin, GPIO_PIN_SET);
	} else {
		HAL_GPIO_WritePin(ASW_S1_GPIO_Port, ASW_S1_Pin, GPIO_PIN_RESET);
	}

	if (chn & 0x4) {
		HAL_GPIO_WritePin(ASW_S2_GPIO_Port, ASW_S2_Pin, GPIO_PIN_SET);
	} else {
		HAL_GPIO_WritePin(ASW_S2_GPIO_Port, ASW_S2_Pin, GPIO_PIN_RESET);
	}

	if (chn & 0x8) {
		HAL_GPIO_WritePin(ASW_S3_GPIO_Port, ASW_S3_Pin, GPIO_PIN_SET);
	} else {
		HAL_GPIO_WritePin(ASW_S3_GPIO_Port, ASW_S3_Pin, GPIO_PIN_RESET);
	}

	if (!chip) {
		HAL_GPIO_WritePin(ASW_EN1_GPIO_Port, ASW_EN1_Pin, GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(ASW_EN2_GPIO_Port, ASW_EN2_Pin, GPIO_PIN_RESET);
	}

	buff_usbtx[0] = 2;
	buff_usbtx[1] = 0;
	USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, buff_usbtx, sizeof(buff_usbtx));
}

void app_ec800_reset(uint8_t state)
{
	if (!state) {
		HAL_GPIO_WritePin(EC800_RST_GPIO_Port, EC800_RST_Pin, GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(EC800_RST_GPIO_Port, EC800_RST_Pin, GPIO_PIN_SET);
	}
}

void app_pwr_4v0(uint8_t state)
{
	if (!state) {
		HAL_GPIO_WritePin(V4_EN_GPIO_Port, V4_EN_Pin, GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(V4_EN_GPIO_Port, V4_EN_Pin, GPIO_PIN_SET);
	}
}

void print_hex(uint8_t *buff, uint32_t size)
{
}